![]() |
||
![]() ![]() Powered by GoldED |
ARexx-Kurs - Teil 2 (von Heiko Kuschel)»ARexx-Kurs: Übersicht1. Einführung in ARexx.
» 2. Programmstrukturen und Ansteuerung von externen Programmen2.0. VorbemerkungenHier wiederhole ich für Quereinsteiger noch einmal einen Teil der Vorbemerkungen, die ich zum ganzen Kurs gemacht habe. Der Kurs wird als reine Text-Datei angefertigt, da auch Amiga aktuell u.a. in ASCII-Form verschickt wird. Um den Text etwas zu gliedern, habe ich daher ein paar "Textmarker" eingefügt. ********** unterteilt einzelne Abschnitte
__________ bezeichnet Beginn und Ende eines ARexx-Programms. Die Striche
gehören nicht zum Programm! Ich hoffe, daß diese Regelung den Kurs etwas leserlicher macht. Wenn Ihr spezielle Fragen habt, etwas nicht verstanden oder Anregungen und Ideen für weitere Kursteile habt, könnt Ihr Euch gern an mich wenden. Ich selbst benutze folgende ARexx-fähige Programme und kann daher auf deren Programmierung kurz eingehen, wenn das gewünscht wird: Wordworth, GoldEd, Database Professional, YAM, Miami, Voyager, TurboCalc. Hier meine Kontaktadresse:
Heiko Kuschel E-Mail: hk0006@wuerzburg.baynet.de Und jetzt... viel Spaß mit ARexx! ****************************************************
-------------------------------- /* Hello World Version 1.3.*/ DO UNTIL Eingabe="Ende" ECHO "Gib was ein!" PARSE PULL Eingabe ECHO "Du hast "||Eingabe||" eingegeben." END -------------------------------- -------------------------------- /* Hello World Version 1.4.*/ DO WHILE Eingabe~="Ende" ECHO "Gib was ein!" PARSE PULL Eingabe ECHO "Du hast "||Eingabe||" eingegeben." END --------------------------------Die Tilde ~ ist das Negationszeichen in ARexx. ~= heißt soviel wie "ist nicht gleich". Die zwei senkrechten Striche verknüpfen Zeichenfolgen miteinander. Die Einrückungen sind zwar nicht nötig, erhöhen aber die Übersichtlichkeit.
Wozu nun diese zwei verschiedenen Möglichkeiten, das offenbar gleiche
auszudrücken (DO WHILE, DO UNTIL)?
DO WHILE überprüft die Bedingung am Anfang der Schleife, Kapiert? Wenn nicht, probiere einmal, in beiden Versionen als erste Zeile nach dem Kommentar einzufügen: -------------------------------- Eingabe="Ende" --------------------------------In Hello World 1.4. wird gar nichts passieren! Die Schleife wird übersprungen, denn die Bedingung ist schon erfüllt. Hello World 1.3. dagegen geht brav in die Schleife rein... und bis zum END hat sich der Wert von Eingabe schon wieder verändert.
Jetzt fehlt uns allerdings noch die dritte Möglichkeit, Schleifen zu
programmieren: DO FOREVER. -------------------------------- /**/ DO FOREVER ECHO "Gib Ende für Quit ein" PARSE PULL Eingabe IF Eingabe="Ende" THEN ECHO "Die eingabe war richtig "||Eingabe LEAVE IF Eingabe ~="Ende" THEN ECHO "Die eingabe war falsch "||Eingabe END -------------------------------- Das ist schon eine ganze Menge, aber es fehlt DO... END, um funktionieren zu können. Also: -------------------------------- /**/ DO FOREVER ECHO "Gib Ende für Quit ein" PARSE PULL Eingabe IF Eingabe="Ende" THEN DO ECHO "Die Eingabe war richtig "||Eingabe LEAVE END IF Eingabe ~="Ende" THEN DO ECHO "Die Eingabe war falsch "||Eingabe END END -------------------------------- Übrigens: IF...THEN kann auch noch mit ELSE (ansonsten) weitergeführt werden. Eine kleine Änderung des obigen Skripts: -------------------------------- /**/ DO FOREVER ECHO "Gib Ende für Quit ein" PARSE PULL Eingabe IF Eingabe="Ende" THEN DO ECHO "Die Eingabe war richtig "||Eingabe LEAVE END ELSE DO ECHO "Die Eingabe war falsch "||Eingabe END END --------------------------------****************************************************
-------------------------------- /*Interpreter V1.0.*/ DO FOREVER PARSE PULL Eingabe IF Eingabe="Ende" THEN LEAVE INTERPRET Eingabe END --------------------------------Tip: Speichere dieses Programm irgendwo auf Festplatte, und nimm "rx (Name des Programms)" in Deine HotKey-Liste auf, falls Du ein Programm hast, das andere Programme auf Tastendruck startet! ****************************************************
Wir haben zwar noch lange nicht alle Möglichkeiten von ARexx selbst ausgeschöpft. Trotzdem möchte ich schon jetzt darauf eingehen, wie Programme angesteuert werden können, die einen ARexx-Port zur Verfügung stellen. Denn einfache Skripte kannst Du jetzt schon selbst schreiben, und am meisten lernt man meiner Erfahrung nach, wenn man selber was ausprobiert. Und wenn's Probleme gibt... Meine Adresse steht am Anfang des Kurses. Um ARexx mitzuteilen, welches Programm angesteuert werden soll, benötigen wir den Befehl ADDRESS. Die ARexx-Adresse (ARexx-Port), die dann folgen muß, entnimmst Du der Dokumentation des jeweiligen Programms. Z.B.: ADDRESS YAM ADDRESS Wordworth.1 ADDRESS TCALC ADDRESS GOLDED.1Eine Liste der vorhandenen Ports erhältst Du mit ECHO SHOW("PORTS") Gib das mal in der ARexx-Shell ein! Der Befehl wird weiter unten genauer erklärt. Nach dem Befehl ADDRESS YAM werden alle Anweisungen, die ARexx nicht versteht, an die YAM-Schnittstelle weitergeleitet. Wenn nun YAM zufällig einen Befehl haben sollte, der auch als ARexx-Befehl existiert, mußt Du ihn in Anführungszeichen setzen, damit er nicht von ARexx selbst interpretiert wird. ADDRESS COMMAND hat eine besondere Bedeutung: Damit können Shell-Befehle aufgerufen werden. -------------------------------- ADDRESS COMMAND DIR --------------------------------listet das aktuelle Verzeichnis auf. -------------------------------- ADDRESS COMMAND DIR --------------------------------hat prinzipiell die gleiche Bedeutung. Im ersten Fall wird aber nur eben schnell der Befehl DIR an COMMAND übergeben, im zweiten Fall wird die Schnittstelle als COMMAND definiert und alle weiteren Befehle an COMMAND geschickt. Also: Ich habe ein Programm, mit dem ich z.B. YAM steuere. Zwischendurch benötige ich einen einzigen COMMAND-Befehl. Dann schreibe ich ihn direkt hinter ADDRESS COMMAND, und alle folgenden Befehle gehen wieder an YAM. ------------------------ ------------------------ ADDRESS YAM ADDRESS YAM (Befehle gehen an YAM) (Befehle gehen an YAM) ADDRESS COMMAND DIR ADDRESS COMMAND DIR (Befehle gehen an YAM) (Befehle gehen an COMMAND) ------------------------ ------------------------(Wenn Du einen proportionalen Zeichensatz installiert hast, wirst Du diesen Vergleich nicht ganz so gut betrachten können. Sorry!) ADDRESS kann auch noch ein paar Parameter mit auf den Weg bekommen: ADDRESS VALUE Variable interpretiert Variable als solche und nimmt den Inhalt der Variablen als neuen ARexx-Port. Z.B.: -------------------------------- Var="YAM" ADDRESS VALUE Var --------------------------------Alle Befehle gehen an YAM.P> ADDRESS ohne weitere Angaben schaltet auf den vorhergehenden ARexx-Port zurück.
Clip : Alle Einträge in der Clip-Liste Files : Eine Liste der offenen logischen Dateinamen Internal : Die interne Port-Liste Libraries : die geöffneten Bibliotheken Ports : die allgemeinen PublicMessagePorts, zu denen auch die ARexx-Ports gehören.Es reicht jeweils die Angabe des ersten Buchstabens.
Wird ein Name angegeben, dann ändert SHOW() seine Funktion. Es gibt 1
zurück, wenn der unter Name angegebene Port gefunden wurde, und 0, wenn er
nicht gefunden wurde. -------------------------------- YAM-Existiert=SHOW("P",YAM) --------------------------------Die dritte Möglichkeit ist die, ein beliebiges Trennzeichen für die Liste anzugeben. Am sinnvollsten ist ein "Wagenrücklauf", was der Return-Taste entspricht. Er hat den ASCII-Code 10 und wird angegeben als D2C(10) (Warum, erkläre ich im nächsten Kursteil.) -------------------------------- ECHO SHOW("P",,D2C(10)) --------------------------------****************************************************
ADDRESS COMMAND sys:rexxc/WaitforPort YAM
Jetzt brauchen wir noch die Möglichkeit, Werte aus Programmen in ARexx zu übernehmen. Das geschieht auf folgende Weise:
a)
b)
c)
Der Befehl ist so definiert, daß er sein Ergebnis (einen Zahlenwert) in
RC ablegt. Das ist meines Erachtens zwar nicht ganz korrekt, aber
durchaus nicht unüblich.
Achtung: Diese Variablen funktionieren nur, wenn vorher die entsprechende
Option eingeschaltet wurde! Das geschieht mit: Die anderen Optionen liefere ich am Ende des Kursteils nach. Sie sind jetzt gerade weniger interessant.
(Ich habe die Nummern der einzelnen Schritte in Kommentarzeilen mit ### eingefügt.) -------------------------------- /* Post abholen mit Miami und YAM */ /* Version 1.0. 9.7.97 Heiko Kuschel */ OPTIONS RESULTS YAMON=1 MIAMION=1 MIAMIONLINE=0 /*Bis hierher werden nur die Variablen so gesetzt, daß*/ /*YAMON=1: angenommen wird, daß YAM gestartet ist */ /*MIAMION=1: das gleiche für Miami */ /*MIAMIONLINE=0: Miami ist offline */ /* ############ Teil 1 ############ */ if ~show(PORTS, YAM) then do address command "run Comm:YAM/YAM" /*Diese Zeile mußt Du ändern!*/ "sys:rexxc/waitforport YAM" YAMON=0 end /* Wenn YAM nicht bereits gestartet ist, dann*/ /* starte es */ /* warte auf den ARexx-Port von YAM */ /* merke dir, daß YAM nicht gestartet war */ /* Natürlich mußt Du den Pfad entsprechend */ /* anpassen. */ /* ############ Teil 2 ############ */ if ~show(PORTS, MIAMI.1) then do Address command "run Comm:miami11a/miami" "sys:rexxc/waitforport MIAMI.1" MIAMION=0 end /* Genau wie bei YAM. */ /* ############ Teil 3 ############ */ address Miami.1 isonline if RC=1 then do MIAMIONLINE=1 end else do ONLINE end /*Hier sind zwei Befehle drin, die zum Befehlsschatz */ /*von Miami gehören: */ /*ISONLINE gibt RC=0 oder 1 zurück */ /*ONLINE geht online. */ /*Die Zeile MIAMIONLINE=1 merkt sich, daß Miami schon*/ /*online war. Sonst wird am Ende des Programms u.U. */ /*eine Verbindung unterbrochen, wo doch Dein Browser */ /*gerade 98% einer 3-Megabyte-Datei geladen hatte... */ /* ############ Teil 4 ############ */ address YAM Mailsendall /* ############ Teil 5 ############ */ Mailcheck if RESULT>0 then YAMON=1 /* ############ Teil 6 ############ */ Mailcheck if RESULT>0 then YAMON=1 /* ############ Teil 7 ############ */ if YAMON=0 then quit /*Das ist der Teil, in dem eigentlich was passiert. */ /*Mailsendall ist ein YAM-Befehl, der alle anstehenden*/ /*Mails sendet. */ /*Mailcheck holt Post ab und gibt in RESULT die Anzahl*/ /*der Mails zurück. */ /*Wenn mehr als 0 Mails abgeholt wurden, dann wird die*/ /*Variable YAMON auf 1 gesetzt. YAM wird dann am Ende */ /*nicht geschlossen, damit Du die neuen Mails auch */ /*lesen kannst. */ /* ############ Teil 8 ############ */ Address MIAMI.1 if MIAMIONLINE=0 then do offline end /*Wenn Miami vorher nicht online war, */ /*geht es jetzt auch wieder offline. */ /* ############ Teil 9 ############ */ if MIAMION=0 then do quit end /*Und wenn Miami gar nicht gestartet war, */ /*wird es jetzt wieder beendet. */ --------------------------------Das Ganze funktioniert leider noch nicht mit YAM 2.0., da dort ARexx noch nicht vollständig implementiert ist. Wenn Du das Skript nutzen willst, mußt Du es mit YAM 1.3.x tun.
Achtung: Lasse das Skript nicht unbeaufsichtigt laufen!
Name.1="Meyer" Kapiert? An den Namen der Variablen wird ein Punkt angehängt, danach kommt eine Zahl. Jeder Name in Verbindung mit jeder Zahl ist eine eigene Variable mit einem eigenen Wert! Das Schöne in ARexx, im Gegensatz zu den meisten anderen Sprachen, die ich kenne:
Du mußt ARexx nicht von vornherein sagen, welches die höchste Zahl ist. Und
man kann auch dem "Stamm" (so heißt der Teil der Variable, den ich als
"Name" bezeichnet habe) einen Wert zuweisen, der dann für alle
Untervariablen gilt. -------------------------------- PLZ.=97280 /*Beachte den Punkt!*/ Zahl=12 echo PLZ.1 echo PLZ.10 echo PLZ.Zahl echo PLZ.PLZ --------------------------------Im letzten Fall wird der Wert der Variablen PLZ.97280 ausgegeben... und der ist auch 97280! Auch mehrdimensionale Variablen sind möglich: Variable.Zahl.Zahl2 Und nun zu dem Programm. Es ist übrigens mit Dokumentation auch im Aminet zu haben, unter util/rexx/WW-Print.lha Außerdem sind noch zwei String-Funktionen drin, die eigentlich erst nächstes Mal behandelt werden sollen. Es sind: LASTPOS(Buchstabe,Zeichenkette) gibt die Position des Buchstabens an, an der er zum letzten Mal in einer Zeichenkette auftritt. -------------------------------- Position=LASTPOS("e","Heiko Kuschel") ECHO Position --------------------------------ergibt 11 LEFT(Zeichenkette,Zahl) ergibt den linken Teil einer Zeichenkette, bis zum xten Zeichen. -------------------------------- ECHO LEFT("Heiko Kuschel",6) --------------------------------ergibt "Heiko" -------------------------------- /* Wordworth 5 ARexx-Skript zum Drucken beliebig vieler Dateien */ /* Heiko Kuschel 27. Juni 1996 */ /* basierend auf WW5-Skript von MJ (Digita) */ /* FREEWARE, falls Digita kein Copyright beansprucht. */ OPTIONS RESULTS Nummer=0 Pfad ="" DO forever Nummer=Nummer+1 RequestFile TITLE "Zu druckendes Dokument wählen..." PATH Pfad File.Nummer = Result /*RequestFile ist ein Wordworth-Befehl. Mit der Option PATH kann wahlweise angegeben werden, welcher Pfad im Requester voreingestellt sein soll.*/ /*Das Resultat der Abfrage steht in RESULT. RC ist größer 0, wenn Abbruch */ /*gewählt wurde.*/ /*Dieses Skript geht davon aus, daß es direkt aus Wordworth gestartet */ /*wurde. Dann ist ADDRESS überflüssig, die Adresse ist bereits richtig */ /*gesetzt. Da Wordworth für jedes Textfenster einen eigenen ARexx-Port*/ /*aufmacht, ist es auch ziemlich schwierig herauszufinden, welchen man */ /*adressieren kann. Wenn ich in WW das erste Fenster schließe, geht der */ /*ARexx-Port mit dem Namen Wordworth.1 mit flöten. Dann kann ich natürlich*/ /*nicht einfach ADDRESS Wordworth.1 schreiben. Ziemlich kompliziert, wie */ /*gesagt. :-( */ Strich=Lastpos("/",File.Nummer) Pfad="" if (Strich>0) then Pfad=Left(File.Nummer,(Strich-1)) /*Hier "extrahiere" ich den Pfad des zuletzt gewählten Dokuments, damit */ /*der Benutzer sich nicht jedesmal durch alle Verzeichnisse und */ /*Unterverzeichnisse durchwühlen muß. Er findet sich im nächsten*/ /*Requester (wenn weitere Dokumente ausgewählt werden) wieder im */ /*gleichen Verzeichnis, in dem er bereits war. */ if (RC > 0) THEN Exit /*Wenn im File-Requester "Abbruch" geklickt wurde, wird das Programm mit */ /*EXIT vollständig abgebrochen.*/ RequestResponse PROMPT "Möchten Sie ein weiteres Dokument drucken?" if (RC > 0) THEN leave /*Frage danach, ob ein weiteres Dokument gedruckt werden soll. Wenn nein, */ /*wird die DO FOREVER-Schleife mit LEAVE verlassen, wenn doch, geht's */ /*oben wieder weiter... mit dem Pfad des zuletzt gewählten Dokuments */ /*als Vorgabe. */ END New Address Value Result /*NEW öffnet ein neues Fenster in Wordworth und gibt in Result den */ /*ARexx-Port zurück. Jedes Wordworth-Fenster hat einen eigenen Port: */ /*Wordworth.1, Wordworth.2 usw. */ Do Zaehler=1 to Nummer Open FILENAME File.Zaehler Print end /*In File.1 steht der Name des ersten zu druckenden Dokuments, */ /*in File.2 der des zweiten usw. */ Close FORCE --------------------------------****************************************************
Wichtig zu wissen ist die Behandlung von Anführungszeichen in ARexx-
Skripten. -------------------------------- ADDRESS TCALC /*Das ist TurboCalcs Adresse*/ variable="Hallo" Put Variable /* Fügt den Wert von Variable in die aktuelle Zeile ein*/ "NACHUNTEN()" /* Setzt den Cursor eine Zeile tiefer */ 'Put Variable' /* Da Variable mit in Anführungszeichen steht, wird */ /* es als Text interpretiert, nicht als der Name einer*/ /* Variablen. In TurboCalc steht in dieser Zeile VARIABLE */ "NACHUNTEN()" Put '"Hallo Du da"' "NACHUNTEN()" Put '"Ich sage mal '||Variable||' zu dir"' 'NACHUNTEN()' 'Put "Ich sage mal '||Variable||' zu dir"' --------------------------------Schau Dir mal mit Trace (vgl. u.) an, was ARexx aus den einzelnen Zeilen macht!
TCO Trace Console Open Öffnet ein eigenes Trace-Fenster TCC Trace Console Close schließt das Fenster wieder TS Trace Start Ab sofort werden alle Befehle in der Form, wie sie ARexx interpretiert, ausgegeben. Ergebnisse werden angezeigt. Der nächste Befehl wird erst nach Drücken von Return ausgeführt. TE Trace End Tracing wird wieder beendet. Für den momentan ausgeführten Befehl muß im Trace-Fenster noch einmal Return gedrückt werden.In der Trace-Console können auch Befehle eingegeben werden, die als Teil des Programms betrachtet werden. = wiederholt die Ausführung der letzten Zeile -x überspringt die nächsten x Befehle In der Trace-Console werden vor der Auflistung der abgearbeiteten Befehle folgende Codes vorangestellt: +++ Befehls- oder Syntaxfehler >C> erweiterter zusammengesetzter Name >F> Ergebnis eines Funktionsaufrufs >L> Sprungmarkenklausel >O> Ergebnis einer zweistelligen Operation >P> Ergebnis einer Präfix-Operation >U> nicht initialisierte Variablen >V> Wert einer Variablen >>> Ergebnis eines Ausdrucks >.> Wert eines "Platzhalter"-TokensEs gibt allerdings auch einen Befehl, der innerhalb eines ARexx-Programms angewendet werden kann. Er heißt sinnvollerweise TRACE und hat eine Menge Optionen: ALL Zeigt alles an. BACKGROUND Es findet keine Ablaufverfolgung statt. Was immer das auch heißt. COMMANDS Zeigt alles an, was an ein externes Programm geschickt wird. ERRORS Zeigt alle Fehler an. (Befehle, die RC~=0 liefern.) INTERMEDIATES Zeigt alle Zwischenwerte an. LABELS Zeigt alle Sprunganweisungen an ( die hatten wir noch nicht). NORMAL Zeigt alle Befehle an, die den voreingestellten Schweregrad (OPTIONS FAILAT x) überschreiten (RC>=x). RESULTS Zeigt alle Ergebnisse an. SCAN Prüft das Skript auf Fehler, ohne es auszuführen OFF Aus. ! Schaltet das Versenden von Befehlen an externe Programme ab, beim zweiten Aufruf wieder an. ? Entspricht TS in DOS. Nach jedem Befehl wird gewartet. Nochmal schaltet den Modus wieder aus.Es reicht jeweils die Angabe des ersten Buchstabens: TRACE R ? kann auch in Verbindung mit den anderen Optionen verwendet werden: TRACE R? Außerdem gibt es die Funktion TRACE()
ECHO TRACE()
IF...THEN...ELSE INTERPRET Ausdruck ADDRESS (VALUE|COMMAND) Ergebnis=SHOW("C|F|I|L|P",Name,Trennzeichen) TRACE Optionen Ergebnis=TRACE() Ergebnis=LASTPOS(Zeichen,Zeichenkette) Ergebnis=LEFT(Zeichenkette,Zahl) OPTIONS [NO] RESULTS die unten genannten Systemvariablen werden (de-)aktiviert FAILAT x RC>=x wird als Fehler interpretiert PROMPT Ausdr.Bei PULL und PARSE PULL wird Ausdr. vorangestellt [NO] CACHE: Der interne Befehlscache, der die Ausführung von Schleifen beschleunigt, wird ab- bzw. angestellt. Normalerweise an. ohne Parameter werden die Einstellungen wieder zurückgesetzt. DOS-Befehle: TCO TCC TS TE WaitForPort Systemvariablen: RESULT RCSo, das war's für diesmal. Ich hoffe, es ist mir gelungen, Dich ein wenig in die Materie einzuführen. Probiere einfach mal aus, Deine eigenen Skripte zu schreiben! Und im Aminet gibt es ein eigenes Verzeichnis util/rexx, in dem auch viele Skripte darauf warten, von Dir erforscht zu werden. Bitte schreibe mir, wenn Du etwas nicht verstanden hast oder bestimmte Probleme hast. Auch, welche Programme Du programmieren willst, und zu welchem Zweck. Wenn möglich, werde ich darauf eingehen.«
![]() ![]() ![]() |
![]() ![]() Ausgabe 03/98![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |